package com.heima.comment.service.impl;

import com.heima.api.user.IUserClient;
import com.heima.comment.pojos.CommentRepay;
import com.heima.comment.pojos.CommentSave;
import com.heima.comment.pojos.LikeRecord;
import com.heima.comment.service.IRepayService;
import com.heima.common.exception.CustomException;
import com.heima.model.comment.dtos.CommentRepayLikeDto;
import com.heima.model.comment.dtos.CommentRepayDto;
import com.heima.model.comment.dtos.CommentRepaySaveDto;
import com.heima.model.comment.vos.CommentRepayVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.utils.common.UserThreadLocal;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @AuthOr: Anna Zhang
 * @Date:2024/8/22-12:12
 * @ClassName:com.heima.comment.service.impl
 * @Description:
 **/
@Slf4j
@Service
@RequiredArgsConstructor
public class RepayServiceImpl implements IRepayService {

    private final MongoTemplate mongoTemplate;

    private final IUserClient userClient;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private final static String SAVE_REPAY = "SAVE_REPAY";
    private final static String LIKE_REPAY = "LIKE_REPAY";
    /**
     * 保存回复的评论
     * @param repaySaveDto
     * @return
     */
    @Override
    @Transactional
    public ResponseResult saveRepayComment(CommentRepaySaveDto repaySaveDto) {
        Boolean mi = stringRedisTemplate.opsForValue().setIfAbsent
                (SAVE_REPAY + UserThreadLocal.get(), "1", 1, TimeUnit.SECONDS);
        if(!mi){
            throw new CustomException(AppHttpCodeEnum.NOT_REPETITION_OPERATION);
        }
        String content = repaySaveDto.getContent();
        if(content.length()>140){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        Boolean flag = checkRepayComment(content);
        if(!flag){
            throw new CustomException(AppHttpCodeEnum.EXIST_SENSITIVE_WORDS);
        }
        CommentRepay repay = new CommentRepay();
        repay.setCommentId(repaySaveDto.getCommentId());
        repay.setContent(repaySaveDto.getContent());
        repay.setAuthorId(UserThreadLocal.get());
        String username = userClient.getUser(UserThreadLocal.get());
        repay.setAuthorName(username);
        repay.setCreatedTime(new Date());
        repay.setLikes(0);
        repay.setReply(0);
        mongoTemplate.save(repay);
        //更新评论的回复数量
        CommentSave comment = mongoTemplate.findById(repaySaveDto.getCommentId(), CommentSave.class);
        if(comment!= null){
            comment.setReply(comment.getReply()+1);
            mongoTemplate.save(comment);
        }
        return new ResponseResult(AppHttpCodeEnum.SUCCESS.getCode(),"评论成功",null,null);
    }

    /**
     * 查询评论的回复列表
     * @param repayDto
     * @return
     */
    @Override
    public ResponseResult loadRepayComment(CommentRepayDto repayDto) {
        if(repayDto.getSize()==null){
            repayDto.setSize(10);
        }
        int num = 1;
        Query query = new Query().addCriteria(Criteria.where("commentId").is(repayDto.getCommentId()))
                .addCriteria(Criteria.where("createdTime").lt(repayDto.getMinDate()))
                .skip((num - 1L) * repayDto.getSize())
                .limit(repayDto.getSize())
                .with(Sort.by(Sort.Direction.DESC, "createdTime"));
        List<CommentRepay> commentRepayList = mongoTemplate.find(query, CommentRepay.class);

        Query query1 = new Query().addCriteria(Criteria.where("authorId").is(UserThreadLocal.get()));
        Map<String, Integer> commentIdMap = mongoTemplate.find(query1, LikeRecord.class).stream().collect(Collectors.toMap(
                LikeRecord::getRepayId, likeRecord -> 1));
        List<CommentRepayVo> collect = commentRepayList.stream().map(one -> {
            CommentRepayVo commentRepayVo = new CommentRepayVo();
            BeanUtils.copyProperties(one, commentRepayVo);
            if (commentIdMap.get(one.getId())!= null){
                commentRepayVo.setOperation((short) 0);
            }
            return commentRepayVo;
        }).collect(Collectors.toList());

        return new ResponseResult(AppHttpCodeEnum.SUCCESS.getCode(),"查询成功",collect,null);
    }

    /**
     * 检测评论内容是否合规
     * @param content
     * @return
     */
    private Boolean checkRepayComment(String content) {
        Map<String, Integer> matchResult = SensitiveWordUtil.matchWords(content);
        if(!CollectionUtils.isEmpty(matchResult)){
            log.info("存在敏感词");
            return false;
        }
        return true;
    }


    /**
     * 点赞回复的评论
     * @param repayLikeDto
     * @return
     */
    @Override
    public ResponseResult likeRepayComment(CommentRepayLikeDto repayLikeDto) {
        Boolean mi = stringRedisTemplate.opsForValue().setIfAbsent
                (LIKE_REPAY + UserThreadLocal.get(), "1", 1, TimeUnit.SECONDS);
        if(!mi){
            throw new CustomException(AppHttpCodeEnum.NOT_REPETITION_OPERATION);
        }
        String commentRepayId = repayLikeDto.getCommentRepayId();
        Query query = Query.query(Criteria.where("id").is(commentRepayId));
        CommentRepay repay = mongoTemplate.findOne(query, CommentRepay.class);
        if(repay==null){
            throw new CustomException(AppHttpCodeEnum.REMARK_NOT_EXIST);
        }
        Integer oldLikeNum = repay.getLikes();
        if(repayLikeDto.getOperation()==0){
            //点赞
            repay.setLikes(oldLikeNum+1);
            mongoTemplate.save(repay);
            //记录到点赞表
            saveLikeRecord(repay);
        }else{
            repay.setLikes(oldLikeNum-1);
            mongoTemplate.save(repay);
            //从点赞记录表删除
            removeLikeRecord(repay);
        }
        HashMap<String, Object> res = new HashMap<>();
        res.put("likes",repay.getLikes());
        return new ResponseResult(AppHttpCodeEnum.SUCCESS.getCode(),"操作成功",res,null);
    }

    /**
     * 移除点赞记录
     * @param repay
     */
    private void removeLikeRecord(CommentRepay repay) {
        Query query = Query.query(Criteria.where("RepayId").is(repay.getId()));
        mongoTemplate.remove(query,LikeRecord.class);
    }

    /**
     * 保存到点赞记录表
     * @param repay
     */
    private void saveLikeRecord(CommentRepay repay) {
        LikeRecord record = new LikeRecord();
        record.setType(1);
        record.setRepayId(repay.getId());
        record.setCreatedTime(new Date());
        record.setAuthorId(UserThreadLocal.get());
        mongoTemplate.save(record);
    }
}
